package com.sz.virtualbank.service.account.impl;

import com.sz.virtualbank.common.exception.BusinessException;
import com.sz.virtualbank.dao.entity.BankCard;
import com.sz.virtualbank.dao.entity.TradeRecord;
import com.sz.virtualbank.dao.entity.User;
import com.sz.virtualbank.dao.mapper.BankCardMapper;
import com.sz.virtualbank.dao.mapper.TradeRecordMapper;
import com.sz.virtualbank.dao.mapper.UserMapper;
import com.sz.virtualbank.service.account.AccountService;
import com.sz.virtualbank.service.transaction.TransactionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 账户服务实现类
 * 
 * @author Claude
 */
@Service
@Slf4j
public class AccountServiceImpl implements AccountService {

    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private TradeRecordMapper tradeRecordMapper;
    
    @Autowired
    private BankCardMapper bankCardMapper;
    
    @Autowired
    private TransactionService transactionService;

    @Override
    public Map<String, BigDecimal> getAccountBalance(Long userId) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        Map<String, BigDecimal> balanceInfo = new HashMap<>();
        balanceInfo.put("balance", user.getBalance());
        balanceInfo.put("frozenAmount", user.getFrozenAmount());
        balanceInfo.put("availableBalance", user.getBalance().subtract(user.getFrozenAmount()));
        
        return balanceInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String recharge(Long userId, BigDecimal amount, String channel, String uniqueToken) {
        // 参数校验
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("充值金额必须大于0");
        }
        
        // 获取用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 处理充值业务
        // 生成交易流水号
        String tradeNo = generateTradeNo("R");
        
        // 更新用户余额
        BigDecimal newBalance = user.getBalance().add(amount);
        userMapper.updateBalance(userId, newBalance);
        
        // 创建交易记录
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setTradeNo(tradeNo);
        tradeRecord.setUserId(userId);
        tradeRecord.setTradeType(1); // 充值
        tradeRecord.setAmount(amount);
        tradeRecord.setBalance(newBalance);
        tradeRecord.setStatus(1); // 成功
        tradeRecord.setChannel(channel);
        tradeRecord.setCreateTime(LocalDateTime.now());
        tradeRecord.setUpdateTime(LocalDateTime.now());
        
        tradeRecordMapper.insert(tradeRecord);
        
        return tradeNo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String withdraw(Long userId, BigDecimal amount, Long bankCardId, String password) {
        // 参数校验
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("提现金额必须大于0");
        }
        
        // 验证支付密码
        if (!verifyPayPassword(userId, password)) {
            throw new BusinessException("支付密码错误");
        }
        
        // 获取用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 检查可用余额
        BigDecimal availableBalance = user.getBalance().subtract(user.getFrozenAmount());
        if (availableBalance.compareTo(amount) < 0) {
            throw new BusinessException("可用余额不足");
        }
        
        // 获取银行卡信息
        BankCard bankCard = bankCardMapper.selectById(bankCardId);
        if (bankCard == null || !bankCard.getUserId().equals(userId)) {
            throw new BusinessException("银行卡不存在或不属于当前用户");
        }
        
        // 处理提现业务
        // 生成交易流水号
        String tradeNo = generateTradeNo("W");
        
        // 更新用户余额
        BigDecimal newBalance = user.getBalance().subtract(amount);
        userMapper.updateBalance(userId, newBalance);
        
        // 创建交易记录
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setTradeNo(tradeNo);
        tradeRecord.setUserId(userId);
        tradeRecord.setTradeType(2); // 提现
        tradeRecord.setAmount(amount);
        tradeRecord.setBalance(newBalance);
        tradeRecord.setStatus(0); // 处理中
        tradeRecord.setChannel("BANK_CARD");
        tradeRecord.setRemark("提现到银行卡" + bankCard.getCardNumber());
        tradeRecord.setCreateTime(LocalDateTime.now());
        tradeRecord.setUpdateTime(LocalDateTime.now());
        
        tradeRecordMapper.insert(tradeRecord);
        
        // 实际应用中，这里可能需要调用外部接口进行实际的提现操作
        // 为了演示，这里直接将状态设置为成功
        tradeRecord.setStatus(1); // 成功
        tradeRecordMapper.update(tradeRecord);
        
        return tradeNo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String transfer(Long userId, String targetAccount, BigDecimal amount, String remark, String password) {
        // 参数校验
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("转账金额必须大于0");
        }
        
        // 验证支付密码
        if (!verifyPayPassword(userId, password)) {
            throw new BusinessException("支付密码错误");
        }
        
        // 获取用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 检查可用余额
        BigDecimal availableBalance = user.getBalance().subtract(user.getFrozenAmount());
        if (availableBalance.compareTo(amount) < 0) {
            throw new BusinessException("可用余额不足");
        }
        
        // 获取目标用户信息
        User targetUser = userMapper.selectByUsername(targetAccount);
        if (targetUser == null) {
            throw new BusinessException("目标账户不存在");
        }
        
        // 不能给自己转账
        if (userId.equals(targetUser.getId())) {
            throw new BusinessException("不能给自己转账");
        }
        
        // 处理转账业务
        // 生成交易流水号
        String tradeNo = generateTradeNo("T");
        
        // 更新用户余额
        BigDecimal senderNewBalance = user.getBalance().subtract(amount);
        userMapper.updateBalance(userId, senderNewBalance);
        
        BigDecimal receiverNewBalance = targetUser.getBalance().add(amount);
        userMapper.updateBalance(targetUser.getId(), receiverNewBalance);
        
        // 创建转出交易记录
        TradeRecord senderRecord = new TradeRecord();
        senderRecord.setTradeNo(tradeNo);
        senderRecord.setUserId(userId);
        senderRecord.setTradeType(3); // 转账
        senderRecord.setAmount(amount.negate()); // 转出为负数
        senderRecord.setBalance(senderNewBalance);
        senderRecord.setTargetAccount(targetAccount);
        senderRecord.setStatus(1); // 成功
        senderRecord.setChannel("INTERNAL");
        senderRecord.setRemark(remark);
        senderRecord.setCreateTime(LocalDateTime.now());
        senderRecord.setUpdateTime(LocalDateTime.now());
        
        tradeRecordMapper.insert(senderRecord);
        
        // 创建转入交易记录
        TradeRecord receiverRecord = new TradeRecord();
        receiverRecord.setTradeNo(generateTradeNo("TR"));
        receiverRecord.setUserId(targetUser.getId());
        receiverRecord.setTradeType(3); // 转账
        receiverRecord.setAmount(amount); // 转入为正数
        receiverRecord.setBalance(receiverNewBalance);
        receiverRecord.setTargetAccount(user.getUsername());
        receiverRecord.setStatus(1); // 成功
        receiverRecord.setChannel("INTERNAL");
        receiverRecord.setRemark("来自" + user.getUsername() + "的转账" + (remark != null ? "，备注：" + remark : ""));
        receiverRecord.setCreateTime(LocalDateTime.now());
        receiverRecord.setUpdateTime(LocalDateTime.now());
        
        tradeRecordMapper.insert(receiverRecord);
        
        return tradeNo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean freezeAmount(Long userId, BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("冻结金额必须大于0");
        }
        
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        BigDecimal availableBalance = user.getBalance().subtract(user.getFrozenAmount());
        if (availableBalance.compareTo(amount) < 0) {
            throw new BusinessException("可用余额不足");
        }
        
        BigDecimal newFrozenAmount = user.getFrozenAmount().add(amount);
        int rows = userMapper.updateFrozenAmount(userId, newFrozenAmount);
        
        return rows > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unfreezeAmount(Long userId, BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("解冻金额必须大于0");
        }
        
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        if (user.getFrozenAmount().compareTo(amount) < 0) {
            throw new BusinessException("冻结金额不足");
        }
        
        BigDecimal newFrozenAmount = user.getFrozenAmount().subtract(amount);
        int rows = userMapper.updateFrozenAmount(userId, newFrozenAmount);
        
        return rows > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String pay(Long userId, BigDecimal amount, String businessType, Long businessId) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("支付金额必须大于0");
        }
        
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        BigDecimal availableBalance = user.getBalance().subtract(user.getFrozenAmount());
        if (availableBalance.compareTo(amount) < 0) {
            throw new BusinessException("可用余额不足");
        }
        
        // 生成交易流水号
        String tradeNo = generateTradeNo("P");
        
        // 更新用户余额
        BigDecimal newBalance = user.getBalance().subtract(amount);
        userMapper.updateBalance(userId, newBalance);
        
        // 创建交易记录
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setTradeNo(tradeNo);
        tradeRecord.setUserId(userId);
        tradeRecord.setTradeType(4); // 支付
        tradeRecord.setAmount(amount.negate()); // 支出为负数
        tradeRecord.setBalance(newBalance);
        tradeRecord.setStatus(1); // 成功
        tradeRecord.setChannel("INTERNAL");
        tradeRecord.setRemark(businessType + "支付，业务ID：" + businessId);
        tradeRecord.setCreateTime(LocalDateTime.now());
        tradeRecord.setUpdateTime(LocalDateTime.now());
        
        tradeRecordMapper.insert(tradeRecord);
        
        return tradeNo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String refund(Long userId, BigDecimal amount, String originalTradeNo) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("退款金额必须大于0");
        }
        
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 查询原交易记录
        TradeRecord originalRecord = tradeRecordMapper.selectByTradeNo(originalTradeNo);
        if (originalRecord == null || !originalRecord.getUserId().equals(userId)) {
            throw new BusinessException("原交易记录不存在或不属于当前用户");
        }
        
        // 生成交易流水号
        String tradeNo = generateTradeNo("RF");
        
        // 更新用户余额
        BigDecimal newBalance = user.getBalance().add(amount);
        userMapper.updateBalance(userId, newBalance);
        
        // 创建交易记录
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setTradeNo(tradeNo);
        tradeRecord.setUserId(userId);
        tradeRecord.setTradeType(5); // 退款
        tradeRecord.setAmount(amount); // 收入为正数
        tradeRecord.setBalance(newBalance);
        tradeRecord.setStatus(1); // 成功
        tradeRecord.setChannel(originalRecord.getChannel());
        tradeRecord.setRemark("原交易退款，交易号：" + originalTradeNo);
        tradeRecord.setCreateTime(LocalDateTime.now());
        tradeRecord.setUpdateTime(LocalDateTime.now());
        
        tradeRecordMapper.insert(tradeRecord);
        
        return tradeNo;
    }

    @Override
    public boolean verifyPayPassword(Long userId, String password) {
        // 本示例中，支付密码与登录密码相同
        // 实际应用中，支付密码应该单独存储和验证
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 这里应该进行加密后的密码比较
        return user.getPassword().equals(password);
    }
    
    /**
     * 生成交易流水号
     *
     * @param prefix 前缀
     * @return 交易流水号
     */
    private String generateTradeNo(String prefix) {
        // 格式：前缀 + 时间戳 + 随机数
        return prefix + System.currentTimeMillis() + String.format("%04d", (int) (Math.random() * 10000));
    }
}
